{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Final Remarks\n",
    "\n",
    "In this Bootcamp we saw how a single algorithm was ported to GPUs using two well-known approaches (Numba and CuPy). Each approach has it strengths and a purpose. From a developer perspective the following are metrics crucial to any development exercise: \n",
    "\n",
    "   1. **Ease of Programming**: Determine what level of processor architectural knowledge a developer needs before starting to convert the serial code to GPU version.\n",
    "   2. **Performance**: Measure how much effort is required to reach desirable performance on a particular architecture.\n",
    "   3. **Portability**: To what extent does the same code run on multiple architectures? What provisions are provided by th chosen programming approach to target different platforms?\n",
    "   4. **Support**: Consider the overall ecosystem and support available from the community.\n",
    "    \n",
    "Let us try to create high-level buckets for each of these above parameters with a limited scope of GPU support:\n",
    "\n",
    "| | |  |  | \n",
    "| :--- | :--- | :--- | :--- |\n",
    "| Ease of Programming | Low: Minimal architecture specific knowledge needed  | Intermediate: Minimal changes expected in code design.  Using these along with architecture knowledge helps in better performance | High: In-Depth GPU architecture knowledge must |\n",
    "| Performance  | Depends: Based on the complexity/type of application the performance may vary | High: Exposes methods to get good performance. These methods are integral part of design and exposed to programmer at various granularities | Best: Full control to developers to control parallelism and memory access |\n",
    "| Portability | Integral: Part of the key objective  | Limited: Works only on specific platform | | \n",
    "| Support | Established: Proven over years and support by multiple vendors for GPU | Emerging: Gaining traction by multiple vendors for GPU  | |\n",
    "\n",
    "There is a very thin line between these categories and within that limited scope and view we could categorize different approaches as follows:\n",
    "\n",
    "\n",
    "\n",
    " \n",
    "| Metrics          | Python CuPy | Python Numba | CUDA Laguages |\n",
    "| ---              | ---         | ---          |    ---        |\n",
    "| **Ease**         | Depends     | Intermediate |    Low        |\n",
    "| **Performance**  | High        |  High        |    Best       |\n",
    "| **Portability**  | Integral    |  Integral    |   Limited     |\n",
    "| **Support**      | Emerging    | Established  |  Established  |\n",
    "\n",
    "The following are points to broaden the user's understanding as there is no \"one-size fits all\" programming model.\n",
    "\n",
    "## Ease of Programming\n",
    "- The Python CuPy programming model is problem-based and it depends on the type of task engaged. A major challenge in Python CuPy is the raw kernel must be written in CUDA C form; however, performance is increased and access to thread IDs (which are not possible with other kernel classes in CuPy) is possible. Because of non-sequential index access within the array, access to thread IDs is required in the serial code task and therefore the CuPy raw kernel was used. A comparable amount of rewriting effort to map the loops onto the CUDA grid of blocks and thread blocks was performed.\n",
    "\n",
    "- Python Numba programming model uses the CUDA C programming paradigm with Python semantics. Moderate effort is required to map the loops onto a grid of blocks and thread of blocks since syntax in Numba are in Python form. \n",
    "\n",
    "## Performance\n",
    "While we have not gone into the details of optimization for any of these programming models the analysis provided here is based on the general design of the programming model itself.\n",
    "- Python CuPy and Numba code optimization is dependent on the logic used in terms of data movement, thread block management and shared memory. However, with emphasis on the lab task, the CuPy approach is expected to have better performance than the Numba approach. \n",
    "\n",
    "## Portability\n",
    "We observed the same code being run on multicore and GPU using CuPy and Numba. The point we highlight here is how a programming model supports the divergent cases where developers may choose to use different kernel classes or function decorators to get more performance. In a real application, the tolerance for this portability/performance trade-off will vary according to the needs of the programmer and application. \n",
    "\n",
    "\n",
    "\n",
    "## Support\n",
    "- CuPy and Numba libraries are well documented and the developer support on GitHub are excellent.  \n",
    "- CuPy implementation is present in the RAPIDS package via conda [here](https://rapids.ai/start.html). \n",
    "- Numba is well support in Anaconda package.\n",
    "- **CUDA Python Ecosystem**: NVIDIA has recently shown support towards the simplification of developers' experience with improved Python code portability and compatibility. The goal is to help unify the Python CUDA ecosystem with a single standard set of low-level interfaces, providing full coverage of, and access to, the CUDA host APIs from Python. The ecosystem allows interoperability among different accelerated libraries and ease of use for Python developers interested in NVIDIA GPUs. The initial release of CUDA Python includes Cython and Python wrappers for the CUDA Driver and runtime APIs. You can read more here:\n",
    "    - [Python Ecosystem](https://developer.nvidia.com/blog/unifying-the-cuda-python-ecosystem/)\n",
    "    - [CUDA Python Public Preview](https://developer.nvidia.com/cuda-python)\n",
    "    - [GPU-Accelerated Computing with Python Numba](https://developer.nvidia.com/how-to-cuda-python)\n",
    "\n",
    "\n",
    "In general parallel computing has been a difficult task that requires developers to not only know a programming approach but to also think in parallel. While this Bootcamp provides you a good start, we recommend participating in the Profiling and Optimization Labs as next steps.\n",
    "\n",
    "-----\n",
    "\n",
    "# <div style=\"text-align: center ;border:3px; border-style:solid; border-color:#FF0000  ; padding: 1em\">[HOME](../_start_nways_python.ipynb)</div>\n",
    "\n",
    "-----\n",
    "\n",
    "# Links and Resources\n",
    "\n",
    "[NVIDIA Nsight System](https://docs.nvidia.com/nsight-systems/)\n",
    "\n",
    "[NVIDIA Nsight Compute](https://developer.nvidia.com/nsight-compute)\n",
    "\n",
    "[NVIDIA CUDA Toolkit](https://developer.nvidia.com/cuda-downloads)\n",
    "\n",
    "**NOTE**: To be able to see the Nsight Systems profiler output, please download the latest version of Nsight Systems from [here](https://developer.nvidia.com/nsight-systems).\n",
    "\n",
    "--- \n",
    "\n",
    "\n",
    "### Other Bootcamps\n",
    "The contents of this Bootcamp originates from [OpenACC GPU Bootcamp Github](https://github.com/gpuhackathons-org/gpubootcamp).  Here are some additional Bootcamp which might of interest : \n",
    "\n",
    "- [AI for HPC](https://github.com/gpuhackathons-org/gpubootcamp/tree/master/hpc_ai/ai_science_climate)\n",
    "\n",
    "\n",
    "## Licensing \n",
    "\n",
    "Copyright © 2022 OpenACC-Standard.org.  This material is released by OpenACC-Standard.org, in collaboration with NVIDIA Corporation, under the Creative Commons Attribution 4.0 International (CC BY 4.0). These materials may include references to hardware and software developed by other entities; all applicable licensing and copyrights apply."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
